#include "stdafx.h"
#include "fmtrec.h"
#include "../comm/sunday.h"

namespace xm
{

	void DiscernWinPE	( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt )
	{
		IMAGE_DOS_HEADER * dhp = (IMAGE_DOS_HEADER*)vpData;
		if( dhp->e_magic != IMAGE_DOS_SIGNATURE ) return;
		SIZE_T off = dhp->e_lfanew;
		if( !off ) return ;
		le::U32 uSig;
		if( off + sizeof(uSig) <= cbData )
		{
			uSig = *(le::U32 *)((UINT8*)vpData + off);
		}
		else
		{
			RFAILEDV(kbsp->Readp( off, &uSig, sizeof(uSig), &off ));
			if( off != sizeof(uSig) ) return ;
		}
		if( uSig == IMAGE_NT_SIGNATURE )
			lpfmt->Push( FMT_PE );
		return;
	}
	void DiscernSWx		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt )
	{
		CONST UINT8 * bp = (CONST UINT8 * )vpData;
		if( bp[1] != 'W' || bp[2] != 'S' ) return ;
		if( bp[0] == 'C' || bp[0] == 'F' || bp[0] == 'Z' )
			lpfmt->Push( FMT_SWX );
	}
	void DiscernDOC		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt )
	{
		static unsigned char data[] = {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1};
		if( memcmp( data, vpData, sizeof(data) ) ) return ;
		lpfmt->Push( FMT_DOC );
	}
	void DiscernTIFF	( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt )
	{
		CONST UINT8* pbHdr = (CONST UINT8*)vpData;
		UINT16 uMark = *(UINT16*)pbHdr;
		if( ( uMark == 'II' && pbHdr[2] == '*' && pbHdr[3] == 00 ) ||
			( uMark == 'MM' && pbHdr[3] == '*' && pbHdr[2] == 00 ) ) 
		{
			lpfmt->Push(FMT_TIFF);
		}
	}
	void DiscernPDF		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt )
	{
		static unsigned char data[] = {0x25, 0x50, 0x44, 0x46};
		if( memcmp( data, vpData, sizeof(data) ) ) return ;
		lpfmt->Push( FMT_PDF );
	}
	void DiscernDEX		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt )
	{
		static unsigned char data[] = {'d', 'e', 'x', 0x0A};
		if( memcmp( data, vpData, sizeof(data) ) ) return ;
		lpfmt->Push( FMT_DEX );
	}
	void DiscernELF		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt )
	{
		static unsigned char data[4] = { 0x7F, 0x45, 0x4C, 0x46 };
		if( memcmp( data, vpData, sizeof(data) ) ) return ;
		lpfmt->Push( FMT_ELF );
	}
	void DiscernXDP		( IKBStream * kbsp, LPCVOID vpData, SIZE_T cbData, IKFormats * lpfmt )
	{
		struct SASP { LPCSTR f; size_t cb; };
		static SASP _wants[] = { 
			STR_SIZE_PAIR("<?xml"),
			STR_SIZE_PAIR("<xdp:xdp"),
		};
		LPCBYTE bpText = (LPCBYTE)vpData;
		LPCBYTE bpTextEnd = bpText + cbData;
		for( size_t i = 0; i < sizeof(_wants)/sizeof(SASP); ++ i )
		{
			bpText = sunday( bpText, bpTextEnd - bpText, (LPCBYTE)_wants[i].f, _wants[i].cb, true );
			if( !bpText ) return ;
		}
		lpfmt->Push( FMT_XDP );
	}

};